
#undef TRUE
#undef FALSE

#include "snes9x.h"
#include "memmap.h"
#include "debug.h"
#include "ppu.h"
#include "snapshot.h"
#include "gfx.h"
#include "display.h"
//#include "apu.h"
//#include "soundux.h"

#define COUNT(a) (sizeof(a) / sizeof(a[0]))

//#define sti() __asm__ __volatile__ ("sti": : :"memory")
//#define cli() __asm__ __volatile__ ("cli": : :"memory")

static int screen_pitch = 132;
uint32 screen_width = 132;
uint32 screen_height = 176;
static int mode = -1;
static bool8 planar = FALSE;
static bool8 in_text_mode = TRUE;
static bool8 stretch = FALSE;

uint8 *off_screen;
uint8 *sub_screen;
uint8 *Delta = NULL;
extern int16 *screen;

static int num_sidewinders = 0;
static bool8 grip_initialised = FALSE;
extern int NumControllers;
static bool8 mouse_installed = FALSE;
static int prev_mouse_x = 0;
static int prev_mouse_y = 0;
static uint32 superscope_turbo = 0;
static uint32 superscope_pause = 0;
static int mouse_offset_x = 0;
static int mouse_offset_y = 0;
static double mouse_scale_h = 1.0;
static double mouse_scale_v = 1.0;
static bool8 wait_for_vsync = FALSE;
static bool8 interpolate = FALSE;

uint32 last_rendered_width = 0;
uint32 last_rendered_height = 0;

extern uint32 joypads [5];

void SaveScreenshot ();

#define ATTRCON_ADDR	0x3c0
#define MISC_ADDR	0x3c2
#define VGAENABLE_ADDR	0x3c3
#define SEQ_ADDR	0x3c4
#define GRACON_ADDR	0x3ce
#define CRTC_ADDR	0x3d4
#define STATUS_ADDR	0x3da

//struct PALLETE {
//  uint8 r,g,b;
//} pal[256];


//unsigned short pal[256];
int pal[256];

/*
typedef struct
{
    int width;
    int height;
    int mode;
} Mode;

static Mode modes [] = {
    {320, 240, GFX_MODEX},	    // 0
    {320, 200, GFX_VGA},	    // 1
    {256, 256, GFX_VGA},	    // 2
    {640, 480, GFX_AUTODETECT},	    // 3
    {640, 480, GFX_VESA1},	    // 4
    {640, 480, GFX_VESA2B},	    // 5
    {640, 480, GFX_VESA2L},	    // 6
    {640, 400, GFX_XTENDED},	    // 7
    {800, 600, GFX_AUTODETECT},	    // 8

    {320, 240, GFX_AUTODETECT},	    // 9
    {640, 480, GFX_AUTODETECT},	    // 10
    {512, 384, GFX_AUTODETECT},	    // 11
    {800, 600, GFX_AUTODETECT}	    // 12
};
*/
/*void S9xInitDisplay () //8bit
{
//	set_color_depth (16);
	//Settings.Transparency = TRUE;
	//Settings.SixteenBit = TRUE;
//	set_color_depth (8);
	Settings.Transparency = FALSE;
	Settings.SixteenBit = FALSE;

    off_screen = (uint8*)malloc ((IMAGE_WIDTH + 2)* IMAGE_HEIGHT);

    GFX.Screen = (uint8 *) off_screen;
    if (!GFX.Screen)
    {
	//fprintf (stdout, "Cannot allocate screen buffer.\n");
	//S9xExit ();
    }
    GFX.Pitch = IMAGE_WIDTH + 2;
	GFX.SubScreen = GFX.Screen;
	GFX.ZBuffer = (uint8 *) malloc ((IMAGE_WIDTH + 2)* IMAGE_HEIGHT);
	GFX.SubZBuffer = NULL;
	sub_screen = NULL;
	Delta = NULL;
    //}
    screen_pitch = IMAGE_WIDTH + 2;
}*/

void S9xInitDisplay () 
{
    GFX.Pitch = IMAGE_WIDTH + 2;
    if (Settings.SixteenBit)
    {
        off_screen = (uint8* )malloc ((IMAGE_WIDTH + 2)* IMAGE_HEIGHT*2);       
        GFX.Screen = (uint8 *) off_screen;
	GFX.Pitch *= 2;
	sub_screen = (uint8*)malloc ((IMAGE_WIDTH + 2)* IMAGE_HEIGHT*2);
	Delta = (uint8*)malloc ((IMAGE_WIDTH + 2) * IMAGE_HEIGHT * 2);
	GFX.SubScreen = (uint8 *) sub_screen;
	GFX.ZBuffer = (uint8 *) malloc ((IMAGE_WIDTH + 2)* IMAGE_HEIGHT);
	GFX.SubZBuffer = (uint8 *) malloc ((IMAGE_WIDTH + 2) * IMAGE_HEIGHT);
    }
    else
    {
        off_screen = (uint8* )malloc ((IMAGE_WIDTH + 2)* IMAGE_HEIGHT);       
        GFX.Screen = (uint8 *) off_screen;
	GFX.SubScreen = GFX.Screen;
	GFX.ZBuffer = (uint8 *) malloc ((IMAGE_WIDTH + 2) * IMAGE_HEIGHT);
	GFX.SubZBuffer = NULL;
	sub_screen = NULL;
	Delta = NULL;
    } 
    screen_pitch = IMAGE_WIDTH + 2;
}


void S9xDeinitDisplay ()
{
    //S9xTextMode ();
	if(off_screen){ free(off_screen); off_screen=0;}
    if(sub_screen){ free(sub_screen); sub_screen=0;}
	if(Delta){ free(Delta); Delta=0;}
    if(GFX.ZBuffer){ free((char *)GFX.ZBuffer); GFX.ZBuffer=0;}
    if(GFX.SubZBuffer){ free((char *)GFX.SubZBuffer); GFX.SubZBuffer=0;}
}

void S9xInitInputDevices ()
{
}

void S9xSetPalette ()
{
    uint16 Brightness = IPPU.MaxBrightness * 140;
	uint8 r,g,b;
    for (int i = 0; i < 256; i++)
    {      
	r = (((PPU.CGDATA [i] >> 0) & 0x1F) * Brightness) >> 8;
	g = (((PPU.CGDATA [i] >> 5) & 0x1F) * Brightness) >> 8;
	b = (((PPU.CGDATA [i] >> 10) & 0x1F) * Brightness) >> 8;               
        pal[i]=(r<<16)|(g<<8)|(b);  
    }
}

void S9xProcessEvents (bool8 block)
{
}

void S9xSetTitle (const char *title)
{
}

extern void REDRAW();
void S9xPutImage (int width, int height) //256 224
{
    REDRAW();    
}

void S9xExtraUsage ()
{

}

void S9xParseDisplayArg (char **argv, int &ind, int)
{
	S9xUsage ();
}


int S9xMinCommandLineArgs ()
{
    return (2);
}

extern int FRAMESKIP_KEY;
void S9xSyncSpeed ()
{
	if (++IPPU.FrameSkip >= /*Settings.SkipFrames*/FRAMESKIP_KEY)
	{
          if ((Settings.SkipFrames == 1)&&(IPPU.FrameCount%3 == 0))
          {
            IPPU.SkippedFrames++;
	    IPPU.RenderThisFrame = FALSE;
          }
          else
          {
	    IPPU.FrameSkip = 0;
	    IPPU.RenderThisFrame = TRUE;
	    IPPU.SkippedFrames = 0;
          }
	}
	else
	{
	    IPPU.SkippedFrames++;
	    IPPU.RenderThisFrame = FALSE;
	}
}


void S9xMessage (int type, int message_no, const char *str)
{
}

